package Entities;

import java.util.ArrayList;

import processing.core.PApplet;
import processing.core.PVector;

import Shapes.Box2D;
import Shapes.Flow;
import Shapes.Node;
import Shapes.pieBall;

public class LCAChain {

	// this kind of material is not raw material, it is made of something
	public ArrayList<Process> Processes = null;

	public String filename = "";
	public String name;
	public String type; // 1-food 2-diet 3-state
	
	//for graphic interface
	public sceneGraph sg = null;
	public int posx,posy,scale;
	
	
	

	// this kind of material is raw material, so it is from somewhere

	public LCAChain() {
	}

	public void setName(String n) {
		this.name = n;
	}

	public String getName() {
		return this.name;
	}

	public void setType(String string) {
		this.type = string;
	}

	public String getType() {
		return this.type;
	}

	public void setProcesses(ArrayList<Process> p) {
		this.Processes = p;
	}

	public ArrayList<Process> getProcesses() {
		return this.Processes;
	}


	public sceneGraph getShape(PApplet p, int centerx, int centery, int scale) {
		sceneGraph sg = new sceneGraph(p);
		sg.setup(centerx, centery, scale);
		sg.generateGraph();
		return sg;
	}

	private Process searchSimilar(String name) {
		// TODO Auto-generated method stub

		for (int i = 0; i < Processes.size(); i++) {
			if (name.equalsIgnoreCase(Processes.get(i).getType())) {
				return Processes.get(i);
			}
		}
		return null;
	}

	public class sceneGraph {

		PApplet app = null;
		pieBall impactBall = null;
		Box2D boundingBox = null;
		
		public int num = Processes.size();
		
		public ArrayList<Node> nodes = new ArrayList<Node>();
		public ArrayList<Flow> flows = new ArrayList<Flow>();
		public ArrayList<Shapes.Ball> balls = new ArrayList<Shapes.Ball>();
		public ArrayList<pieBall> impactballs = new ArrayList<pieBall>();
		
		int posx, posy, scale;

		sceneGraph(PApplet p) {
			this.app = p;
		}

		public void setup(int x, int y, int s) {
			this.posx = x;
			this.posy = y;
			this.scale = s;
		}

		/**
		 * this method can only be called once, because all the graphics will be
		 * cleaned and renewed.
		 */

		public void generateGraph() {

			if (nodes.size() != 0) {
				nodes.clear();
			}

			if (balls.size() != 0) {
				balls.clear();
			}

			if (flows.size() != 0) {
				flows.clear();
			}

			float angle = (float) (2 * Math.PI * 1.0 / (num + 1));
			int tempx;
			int tempy;
			
			ArrayList<String> impactname = new ArrayList<String>();

			for (int i = 0; i < getProcesses().size(); i++) {
							
				tempx = (int) (this.posx + (float) (scale/3 * Math.sin(angle * i)));
				tempy = (int) (this.posy - (float) (scale/3 * Math.cos(angle * i)));
			
				getProcesses().get(i).setupGraph(tempx, tempy, scale/3, i);
				
				for(int j = 0; j < getProcesses().get(i).getImpact().size();j++){
					String s = getProcesses().get(i).getImpact().get(j).type + " " +getProcesses().get(i).getImpact().get(j).name + " " + getProcesses().get(i).getImpact().get(j).quantity + " " +getProcesses().get(i).getImpact().get(j).unit;
					impactname.add(s);
				}
				
				
				nodes.add(getProcesses().get(i).getCheckBox(app));    //ok
		//   	flows.add(getProcesses().get(i).getFlowmass(app));
				balls.add(getProcesses().get(i).getCenterBall(app));    //ok
				
				if(i!=0){
					//float speed = getProcesses().get(i-1).getDuration();
					float speed = 5;
					flows.add(getProcesses().get(i).getFlowmass(app,nodes.get(i-1).posx,nodes.get(i-1).posy,nodes.get(i).posx,nodes.get(i).posy,speed));		                                                                                                       
				}
			}

			generateImpactBalls(impactname);
			
		
		}

		
		
		
		private void generateImpactBalls(ArrayList<String> impactname) {
			// TODO Auto-generated method stub
			
			ArrayList<String> landimpact = new ArrayList<String>();
			ArrayList<String> gasimpact = new ArrayList<String>();
			for(int i = 0; i < impactname.size(); i ++){
				String[] ss = impactname.get(i).split(" ");
				if(ss[0].equalsIgnoreCase("land")){
					landimpact.add(impactname.get(i));
				}else if(ss[0].equalsIgnoreCase("GHG")){
					gasimpact.add(impactname.get(i));
				}
			}
			
			pieBall pie1 = new pieBall(app);
			pie1.setup("land", posx, posy, scale/5, landimpact);
			pie1.setName("land");
		//	pie1.generateTreeFromString(landimpact);
			this.impactballs.add(pie1);
			
			pieBall pie2 = new pieBall(app);
			pie2.setup("GHG", posx, posy, scale/5, gasimpact);
			pie2.setName("GHG");
		//	pie2.generateTreeFromString(gasimpact);
			this.impactballs.add(pie2);
			
		}
		

		public ArrayList<pieBall> getImpactBalls(){
			return this.impactballs;
		}
		
		
		public ArrayList<Node> getNodes() {
			return this.nodes;
		}

		public ArrayList<Shapes.Ball> getBalls() {
			return this.balls;
		}

		public ArrayList<Flow> getFlows() {
			return this.flows;
		}

		// -------------------------this part is for the interactive operation
		// -----------------//
		private int getPosition(int sectionX, int sectionY) {
			// TODO Auto-generated method stub

			if (balls.size() == 0) {
				return 0;
			}
			int position = 0;
			float distance = 1000;

			for (int i = 0; i < balls.size(); i++) {
				PVector m = new PVector(balls.get(i).xpos, balls.get(i).ypos);
				float tem = m.dist(new PVector(app.mouseX, app.mouseY));
				if (distance > tem) {
					distance = tem;
					position = i;
				}
			}

			float temx = balls.get(position).tempxpos;
			float temy = balls.get(position).tempypos;

			if ((sectionX > posx / 2) && (sectionY > posy / 2)) {
				if ((sectionX < temx) && (sectionY > temy)) {
				} else {
					position += 1;
				}
			} else if ((sectionX > posx / 2)
					&& (sectionY < posy / 2)) {
				{
					if ((sectionX > temx) && (sectionY > temy)) {
					} else {
						position += 1;
					}
				}
			} else if ((sectionX < posx / 2)
					&& (sectionY < posy / 2)) {
				if ((sectionX > temx) && (sectionY < temy)) {
				} else {
					position += 1;
				}
			} else {
				if ((sectionX > temx) && (sectionY > temy)) {
				} else {
					position += 1;
				}
			}
			return position;
		}

		boolean addOneProcess(String name, int sectionX, int sectionY) {
			// TODO Auto-generated method stub

			int position = this.getPosition(sectionX, sectionY);
			
			Process newp = new Process();
			
			if (searchSimilar(name) != null) {
				newp.copyProcess(searchSimilar(name));
			} else {
				newp.setType(name);
			}

			Processes.add(newp);
			for (int change = Processes.size() - 1; change > position; change--) {
				Processes.set(change, Processes.get(change - 1));
			}
			Processes.set(position, newp);

		//	this.generateGraph();
			return true;
		}

		

	}

}
